import os
from collections import OrderedDict

from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet
from django.http import FileResponse

from .serializer import *
from util.auth import OWNTokenAuthentication
from util.page import MyPageNumberPagination
from util.exception import ValidationError
from apps.missions.tasks import *


class MissionViewSet(GenericViewSet):
    authentication_classes = [OWNTokenAuthentication]

    @action(detail=False, methods=["GET", ], url_path="list")
    def mission_list(self, requests, *args, **kwargs):
        misson_number = requests.GET.get("mission_number")
        state = requests.GET.get("state")
        start_date = requests.GET.get("start_date")
        end_date = requests.GET.get("end_date")
        gateway_id = requests.GET.get("gateway_id")
        sensor_number = requests.GET.get("sensor_number")
        order = requests.GET.get("order")
        data = {}
        data["mission_number"] = misson_number if misson_number else None
        data["state"] = state if state else None
        data["start_date"] = start_date if start_date else None
        data["end_date"] = end_date if end_date else None
        data["gateway_id"] = gateway_id if gateway_id else None
        data["sensor_number"] = sensor_number if sensor_number else None
        if order:
            data["order"] = int(order)
        else:
            data["order"] = -1
        check_seriailizer = MissionSerializerSearch(data=data)
        if check_seriailizer.is_valid():
            data = check_seriailizer.validated_data
            mission_number = data.get("mission_number")
            state = data.get("state")
            start_date = data.get("start_date")
            end_date = data.get("end_date")
            order = data.get("order")
            gateway_id = data.get("gateway_id")
            sensor_number = data.get("sensor_number")
            missions = Mission.objects
            if mission_number:
                missions = missions.filter(mission_number=mission_number)
            if gateway_id:
                missions = missions.filter(gateway_id__icontains=gateway_id)
            if sensor_number:
                missions = missions.filter(sensor_number=sensor_number)
            if state is not None:
                missions = missions.filter(state=state)
            if start_date:
                missions = missions.filter(create_date__gt=start_date, create_date__lt=end_date)
            if order == 1:
                missions = missions.order_by("create_date")
            else:
                missions = missions.order_by("-create_date")
            if mission_number != 8:
                missions = missions.filter(is_delete=False).exclude(mission_number=8).all()
            else:
                missions = missions.filter(is_delete=False).all()
            page = MyPageNumberPagination()
            page_mission = page.paginate_queryset(queryset=missions, request=requests, view=self)
            mission_re = MissionSerializerListList(instance=page_mission, many=True)
            return Response(self.__get_paginated_response(page, requests, mission_re.data))
        else:
            raise ValidationError(20001)

    def __get_paginated_response(self, page, request, datas):
        a = OrderedDict([
            ('current', int(page.get_page_number(request, page))),
            ('total', int(page.page.paginator.count)),
            ('pageSize', int(page.get_page_size(request))),
            ('data', datas)
        ])
        return a

    # 批量任务
    @action(detail=False, methods=["post", ], url_path="create")
    def mission_do(self, requests, *args, **kwargs):
        data = {}
        data["key_list"] = requests.data.get("key_list")
        data["mission_number"] = requests.data.get("mission_number")
        data["sensor_list"] = requests.data.get("sensor_list")
        data["mission_parameter"] = requests.data.get("mission_parameter")
        data["end_date"] = requests.data.get("end_date")
        serializer = MissionSerializercreate(data=data)
        if serializer.is_valid():
            # 发起异步任务
            data = serializer.create(serializer.validated_data)
            mission_number = serializer.validated_data.get("mission_number")
            mission_parameter = serializer.validated_data.get("mission_parameter")
            mfile = MFileModel.objects.filter(id=mission_parameter).first()
            mission_parameter = mfile.filepath if mfile else mission_parameter
            self.__delay_mission(mission_number, mission_parameter, data)
            return Response({"code": 200, "msg": "添加任务成功"})
        else:
            raise ValidationError(20001)

    def __delay_mission(self, mission_number, mission_parameter, data):
        mission_id_list = data.get("mission_id_list")
        if mission_number == settings.REBOOT_GATEWAY:
            for mission_id in mission_id_list:
                reboot_gateway_task.delay({"mission_id": mission_id})
        if mission_number == settings.POWEROFF:
            for mission_id in mission_id_list:
                poweroff_gateway_task.delay({"mission_id": mission_id})
        elif mission_number == settings.REBOOT_SENSOR:
            for mission_id in mission_id_list:
                reboot_sensor_task.delay({"mission_id": mission_id})
        elif mission_number == settings.READ_GATEWAY:
            for mission_id in mission_id_list:
                read_gateway_task.delay({"mission_id": mission_id})
        elif mission_number == settings.READ_SENSOR:
            for mission_id in mission_id_list:
                read_sensor_task.delay({"mission_id": mission_id})
        elif mission_number == settings.UPDATE_GATEWAY:
            for mission_id in mission_id_list:
                upload_gateway_task.delay({"mission_id": mission_id, "file_name": mission_parameter})
        elif mission_number == settings.UPDATE_SENSOR:
            for mission_id in mission_id_list:
                upload_sensor_task.delay({"mission_id": mission_id, "file_name": mission_parameter})
        elif mission_number == settings.DOWN_SCRIPT:
            for mission_id in mission_id_list:
                down_script_task.delay({"mission_id": mission_id, "file_name": mission_parameter})
        elif mission_number == settings.DOWN_DEPLOY:
            for mission_id in mission_id_list:
                down_deploy_task.delay({"mission_id": mission_id})
        elif mission_number == settings.GET_DATA:
            for mission_id in mission_id_list:
                get_data_task.delay({"mission_id": mission_id})
        elif mission_number == settings.AGREEMENT_GATEWAY:
            for mission_id in mission_id_list:
                agreement_task.delay({"mission_id": mission_id, "file_name": mission_parameter})
        elif mission_number == settings.MAIN_GATEWAY:
            for mission_id in mission_id_list:
                main_task.delay({"mission_id": mission_id, "file_name": mission_parameter})
        elif mission_number == settings.CONFIG_GATEWAY:
            for mission_id in mission_id_list:
                config_task.delay({"mission_id": mission_id, "file_name": mission_parameter})
        elif mission_number == settings.QUERY_SIM:
            for mission_id in mission_id_list:
                query_sim.delay({"mission_id": mission_id})

    @action(detail=False, methods=["GET", ], url_path="files_read")
    def files_read(self, requests, *args, **kwargs):
        try:
            file_type = int(requests.GET.get("file_type"))
        except:
            file_type = 0
        if file_type == 0:
            file_path = settings.UPDATE_GATEWAY_FILE_PATH
        else:
            file_path = settings.UPDATE_SENSOR_FILE_PATH
        os.chdir(file_path)
        files = os.listdir()
        results = []
        for name in files:
            results.append({
                "key": name,
                "name": name
            })
        return Response({
            "code": 200,
            "result": results
        })

    @action(detail=False, methods=["POST", ], url_path="files_write")
    def files_write(self, requests, *args, **kwargs):
        try:
            file_type = int(requests.data.get("file_type"))
        except:
            file_type = 0
        myFile = requests.FILES.get("file")
        name = myFile.name
        if file_type == 0:
            file_path = settings.UPDATE_GATEWAY_FILE_PATH
        else:
            file_path = settings.UPDATE_SENSOR_FILE_PATH
        destination = open(os.path.join(file_path, name), "wb+")
        for chunk in myFile.chunks():
            destination.write(chunk)
        destination.close()
        return Response({
            "code": 200,
            "msg": "上传成功"
        })

    @action(detail=False, methods=["GET", ], url_path="down_file")
    def down_file(self, requests, *args, **kwargs):
        mission_id = requests.GET.get("mission_id")
        mission = Mission.objects.filter(id=mission_id).first()
        if mission:
            file_path = mission.file_path
            if os.path.exists(file_path):
                if os.path.isfile(file_path):
                    try:
                        file_paths = file_path.split("/")
                        file_name = file_paths[-1]
                        file = open(file_path, 'rb')
                        response = FileResponse(file)
                        response['Content-Type'] = 'application/octet-stream'
                        response['Content-Disposition'] = 'attachment;filename="{}"'.format(file_name)
                        return response
                    except:
                        raise ValidationError(70002)
            else:
                raise ValidationError(50004)
        else:
            raise ValidationError(80001)

    # 批量任务
    @action(detail=False, methods=["post", ], url_path="log")
    def mission_log(self, requests, *args, **kwargs):
        data = {}
        data["key"] = requests.data.get("key")
        data["mission_number"] = requests.data.get("mission_number")
        data["sensor_id"] = requests.data.get("sensor_id")
        data["start_date"] = requests.data.get("start_date")
        data["end_date"] = requests.data.get("end_date")
        serializer = MissionLogSerializercreate(data=data)
        if serializer.is_valid():
            # 发起异步任务
            mission_id_list = serializer.create(serializer.validated_data)
            for mission_id in mission_id_list:
                data = {"mission_id": mission_id}
                log_task.delay(data)
            return Response({"code": 200, "msg": "添加任务成功"})
        else:
            raise ValidationError(20001)

    # 批量任务
    @action(detail=False, methods=["get", ], url_path="remove")
    def remove(self, requests, *args, **kwargs):
        data = {}
        data["mission_id"] = requests.GET.get("mission_id")
        serializer = MissionRemoveSerializercreate(data=data)
        if serializer.is_valid():
            # 发起异步任务
            serializer.remove(serializer.validated_data)
            return Response({"code": 200, "msg": "删除成功"})
        else:
            raise ValidationError(20001)
